package com.seantone.xsdk_flutter;

import android.app.Activity;
import android.app.Application;
import android.os.Bundle;
import android.os.Debug;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.google.gson.Gson;
import com.seantone.xsdk.core.XSDK;
import com.seantone.xsdk.core.impl.IIAPCallback;
import com.seantone.xsdk.core.impl.IXSDKCallback;
import com.seantone.xsdk.core.impl.ad.IBannerAd;
import com.seantone.xsdk.core.impl.ad.IBannerAdEventCallBack;
import com.seantone.xsdk.core.impl.ad.IRewardedVideoAd;
import com.seantone.xsdk.core.impl.ad.IRewardedVideoAdEventCallBack;
import com.seantone.xsdk.core.impl.ad.ISplashAD;
import com.seantone.xsdk.core.impl.ad.ISplashADCallBack;

import java.util.HashMap;
import java.util.Map;

import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.EventChannel;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;

/** XsdkFlutterPlugin */
public class XsdkFlutterPlugin implements FlutterPlugin, MethodCallHandler {
  /// The MethodChannel that will the communication between Flutter and native Android
  ///
  /// This local reference serves to register the plugin with the Flutter Engine and unregister it
  /// when the Flutter Engine is detached from the Activity
  private MethodChannel channel;
  private Activity mActivity = null;

  //=============================传递消息到flutter的Event事件======================================
  // 事件派发对象
  private  EventChannel.EventSink eventSink = null;
  // 事件派发流
  private  EventChannel.StreamHandler streamHandler = new  EventChannel.StreamHandler(){
    @Override
    public void onListen(Object arguments, EventChannel.EventSink events) {
      eventSink = events;
    }

    @Override
    public void onCancel(Object arguments) {
      eventSink = null;
    }
  };
  EventChannel eventChannel = null;
  //==============================================================================

  private Map<Integer, IBannerAd> bannerAdMap = new HashMap<Integer, IBannerAd>();
  private Map<Integer, IRewardedVideoAd> videoAdMap = new HashMap<Integer, IRewardedVideoAd>();
  private Map<Integer, ISplashAD> splashADMap = new HashMap<Integer, ISplashAD>();

  static int num = 1;

  Integer genNumber()
  {
    return num++;
  }

  public static void printLoadedClass() {

   // Debug.printLoadedClasses(2);

  }

  @Override
  public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {

      Application content =  (Application)flutterPluginBinding.getApplicationContext();
    Application.ActivityLifecycleCallbacks callbacks = new Application.ActivityLifecycleCallbacks() {

      @Override
      public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle bundle) {

      }

      @Override
      public void onActivityStarted(@NonNull Activity activity) {
        content.unregisterActivityLifecycleCallbacks(this);

        mActivity = activity;
//        Log.d("xsdk", "======");
        XSDK.getInstance().init(mActivity);
        printLoadedClass();
      }

      @Override
      public void onActivityResumed(@NonNull Activity activity) {

      }

      @Override
      public void onActivityPaused(@NonNull Activity activity) {

      }

      @Override
      public void onActivityStopped(@NonNull Activity activity) {

      }

      @Override
      public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle bundle) {

      }

      @Override
      public void onActivityDestroyed(@NonNull Activity activity) {
        mActivity = null;
      }
    };

    content.registerActivityLifecycleCallbacks(callbacks);

    channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "xsdk_flutter");
    channel.setMethodCallHandler(this);

    eventChannel = new EventChannel(flutterPluginBinding.getBinaryMessenger(), "xsdk_flutter_event");
    eventChannel.setStreamHandler(streamHandler);
  }

  @Override
  public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
   if(call.method.equals("hasSDK")){
      result.success(XSDK.hasSDK(call.arguments().toString()));
    }else if(call.method.equals("isInitSDK")){
      result.success(XSDK.getInstance().isInitSDK(call.arguments().toString()));
   } else if(call.method.equals("initSDK")){
      XSDK.initSDK(call.arguments().toString(), new IXSDKCallback() {
        @Override
        public void onSuccess(String ret) {
          result.success(ret);
        }

        @Override
        public void onFaild(String ret) {
          result.error("onFaild", ret, ret);
        }
      });
    } else if(call.method.equals("login")){
      XSDK.login(call.arguments().toString(), new IXSDKCallback() {
        @Override
        public void onSuccess(String ret) {
          result.success(ret);
        }

        @Override
        public void onFaild(String ret) {
          result.error("onFaild", ret, ret);
        }
      }) ;
    }else if(call.method.equals("logout")){
      XSDK.logout(call.arguments().toString(),  new IXSDKCallback() {
        @Override
        public void onSuccess(String ret) {
          result.success(ret);
        }

        @Override
        public void onFaild(String ret) {
          result.error("onFaild", ret, ret);
        }
      }) ;
    }
    else if(call.method.equals("postEvent")){
      XSDK.postEvent(call.arguments().toString()) ;
      result.success(null);
    }
    else if(call.method.equals("pay")){
      XSDK.pay(call.arguments().toString(), new IXSDKCallback() {
        @Override
        public void onSuccess(String ret) {
          result.success(ret);
        }

        @Override
        public void onFaild(String ret) {
          result.error("onFaild", ret, ret);
        }
      }); ;
    }else if(call.method.equals("requestProduct")){
     XSDK.requestProduct(call.arguments().toString(), new IXSDKCallback() {
       @Override
       public void onSuccess(String ret) {
         result.success(ret);
       }

       @Override
       public void onFaild(String ret) {
         result.error("onFaild", ret, ret);
       }
     }); ;
   }else if(call.method.equals("queryProduct")){
     XSDK.queryProduct(call.arguments().toString(), new IXSDKCallback() {
       @Override
       public void onSuccess(String ret) {
         result.success(ret);
       }

       @Override
       public void onFaild(String ret) {
         result.error("onFaild", ret, ret);
       }
     }); ;
   }
    else if(call.method.equals("share")){
      XSDK.share(call.arguments().toString(), new IXSDKCallback() {
        @Override
        public void onSuccess(String ret) {
          result.success(ret);
        }

        @Override
        public void onFaild(String ret) {
          result.error("onFaild", ret, ret);
        }
      });

    } else if(call.method.equals("onIPAEvent")){
      XSDK.getInstance().onIPAEent(ret -> {
        HashMap<String, Object> d = new HashMap<>();
        d.put("method", "onIPAEvent");
        d.put("data", new Gson().toJson(ret));
        eventSink.success(new Gson().toJson(d));
      });
   }


    else if(call.method.equals("createBannerAd")){
      int objectId = genNumber();
      IBannerAd bannerAd =  XSDK.createBannerAd(call.arguments().toString(), new IBannerAdEventCallBack() {
        @Override
        public void onLoad(String ret) {
          HashMap<String, Object> d = new HashMap<>();
          d.put("ret", ret);
          d.put("method", "onLoad");
          d.put("objectId", objectId);
          d.put("event", "createBannerAd");
          eventSink.success(new Gson().toJson(d));
        }

        @Override
        public void onHide() {
          HashMap<String, Object> d = new HashMap<>();
          d.put("method", "onHide");
          d.put("objectId", objectId);
          d.put("event", "createBannerAd");
          eventSink.success(new Gson().toJson(d));
        }

        @Override
        public void onError(String ret) {
          HashMap<String, Object> d = new HashMap<>();
          d.put("method", "onError");
          d.put("objectId", objectId);
          d.put("event", "createBannerAd");
          eventSink.success(new Gson().toJson(d));
        }
      });
      bannerAdMap.put(objectId, bannerAd);
      result.success(objectId);
    }else if(call.method.equals("showBannerAd")){
      try{
        HashMap  data = new Gson().fromJson(call.arguments().toString(), HashMap.class);
        if(!data.containsKey("objectId")) return;
        double objectId = (double)data.get("objectId");
        IBannerAd bannerAd =  bannerAdMap.get((int)objectId);
        if( bannerAd == null) return;
        bannerAd.show(data.get("params").toString());
      }finally {
        result.success(null);
      }
    }else if(call.method.equals("hideBannerAd")){
      try{
        HashMap  data = new Gson().fromJson(call.arguments().toString(), HashMap.class);
        if(!data.containsKey("objectId")) return;
        double objectId = (double)data.get("objectId");
        IBannerAd bannerAd =  bannerAdMap.get((int)objectId);
        if( bannerAd == null) return;
        bannerAd.hide();
      }finally {
        result.success(null);
      }
    }else if(call.method.equals("destoryBannerAd")){
      try{
        HashMap  data = new Gson().fromJson(call.arguments().toString(), HashMap.class);
        if(!data.containsKey("objectId")) return;
        double objectId = (double)data.get("objectId");
        IBannerAd bannerAd =  bannerAdMap.get((int)objectId);
        if( bannerAd == null) return;
        bannerAd.destory();
        bannerAdMap.remove((int)objectId);
      }finally {
        result.success(null);
      }
    }
    else if(call.method.equals("createRewardedVideoAd")){
      int objectId = genNumber();
      IRewardedVideoAd videoAd =  XSDK.createRewardedVideoAd(call.arguments().toString(), new IRewardedVideoAdEventCallBack() {
        @Override
        public void onError(String ret) {
          HashMap<String, Object> d = new HashMap<>();
          d.put("ret", ret);
          d.put("event", "createRewardedVideoAd");
          d.put("method", "onError");
          d.put("objectId", objectId);

          eventSink.success(new Gson().toJson(d));
        }

        @Override
        public void onLoad(String ret) {
          HashMap<String, Object> d = new HashMap<>();
          d.put("ret", ret);
          d.put("method", "onLoad");
          d.put("event", "createRewardedVideoAd");
          d.put("objectId", objectId);
          eventSink.success(new Gson().toJson(d));
        }

        @Override
        public void onReward() {
          HashMap<String, Object> d = new HashMap<>();
          d.put("method", "onReward");
          d.put("event", "createRewardedVideoAd");
          d.put("objectId", objectId);
          eventSink.success(new Gson().toJson(d));
        }

        @Override
        public void onClose() {
          HashMap<String, Object> d = new HashMap<>();
          d.put("method", "onClose");
          d.put("event", "createRewardedVideoAd");
          d.put("objectId", objectId);
          eventSink.success(new Gson().toJson(d));
        }
      });
      videoAdMap.put(objectId, videoAd);
      result.success(objectId);
    }
    else if(call.method.equals("showRewardedVideoAd")){
      try{
        HashMap  data = new Gson().fromJson(call.arguments().toString(), HashMap.class);
        if(!data.containsKey("objectId")) return;
        double objectId = (double)data.get("objectId");
        IRewardedVideoAd videoAd  =  videoAdMap.get((int)objectId);
        if( videoAd == null) return;
        videoAd.show();
      }finally {
        result.success(null);
      }
    }else if(call.method.equals("destoryRewardedVideoAd")){
      try{
        HashMap  data = new Gson().fromJson(call.arguments().toString(), HashMap.class);
        if(!data.containsKey("objectId")) return;
        double objectId = (double)data.get("objectId");
        IRewardedVideoAd videoAd  =  videoAdMap.get((int)objectId);
        if( videoAd == null) return;
        videoAd.destory();
        videoAdMap.remove((int)objectId);
      }finally {
        result.success(null);
      }
    }else if(call.method.equals("createSplashAD")){
      int objectId = genNumber();
      ISplashAD splashAD =  XSDK.createSplashAD(call.arguments().toString(), new ISplashADCallBack() {

        @Override
        public void onDismissed() {
          HashMap<String, Object> d = new HashMap<>();
          d.put("method", "onDismissed");
          d.put("event", "createSplashAD");
          d.put("objectId", objectId);
          eventSink.success(new Gson().toJson(d));
        }

        @Override
        public void onLoad(String ret) {
          HashMap<String, Object> d = new HashMap<>();
          d.put("method", "onLoad");
          d.put("ret", ret);
          d.put("event", "createSplashAD");
          d.put("objectId", objectId);
          eventSink.success(new Gson().toJson(d));
        }

        @Override
        public void onError(String ret) {
          HashMap<String, Object> d = new HashMap<>();
          d.put("method", "onError");
          d.put("ret", ret);
          d.put("event", "createSplashAD");
          d.put("objectId", objectId);
          eventSink.success(new Gson().toJson(d));
        }

        @Override
        public void onClicked() {
          HashMap<String, Object> d = new HashMap<>();
          d.put("method", "onClicked");
          d.put("event", "createSplashAD");
          d.put("objectId", objectId);
          eventSink.success(new Gson().toJson(d));
        }
      });
      splashADMap.put(objectId, splashAD);
      result.success(objectId);
    }else if( call.method.equals("showSplashAd")){
      try{
        HashMap  data = new Gson().fromJson(call.arguments().toString(), HashMap.class);
        if(!data.containsKey("objectId")) return;
        double objectId = (double)data.get("objectId");
        ISplashAD splashAD =  splashADMap.get((int)objectId);
        if( splashAD == null) return;
        splashAD.show(data.get("params").toString());
      }finally {
        result.success(null);
      }
    }else if( call.method.equals("destorySplashAd")){
      try{
        HashMap  data = new Gson().fromJson(call.arguments().toString(), HashMap.class);
        if(!data.containsKey("objectId")) return;
        double objectId = (double)data.get("objectId");
        ISplashAD splashAD =  splashADMap.get((int)objectId);
        if( splashAD == null) return;
        splashAD.destory();
        splashADMap.remove((int)objectId);
      }finally {
        result.success(null);
      }
    }
    else {
      result.notImplemented();
    }
  }

  @Override
  public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
    channel.setMethodCallHandler(null);
    eventChannel.setStreamHandler(null);
  }
}
